package com.liuya.safe.policy.controller;

import java.io.IOException;
import java.io.StringReader;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.google.gson.Gson;
import com.liuya.common.SpringUtils;
import com.liuya.common.StringUtil;
import com.liuya.common.WebUtil;
import com.liuya.base.BaseController;
import com.liuya.db.TableView;
import com.liuya.safe.exception.AuthException;
import com.liuya.safe.model.SafeQuery;
import com.liuya.safe.policy.handler.QueryDesignHandler;
import com.liuya.safe.policy.handler.QueryRawHandler;
import com.liuya.safe.policy.handler.QueryTestHandler;
import com.liuya.safe.policy.service.QueryManagerService;
import com.liuya.safe.util.AuthUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import com.liuya.db.sql.xml.BinaryExpression;
import com.liuya.db.sql.xml.Column;
import com.liuya.db.sql.xml.ContextValue;
import com.liuya.db.sql.xml.ExpressionGroupTypeItem;
import com.liuya.db.sql.xml.InExpression;
import com.liuya.db.sql.xml.IsNotNullExpression;
import com.liuya.db.sql.xml.IsNullExpression;
import com.liuya.db.sql.xml.NotInExpression;
import com.liuya.db.sql.xml.Operand;
import com.liuya.db.sql.xml.Operand1;
import com.liuya.db.sql.xml.Operand2;
import com.liuya.db.sql.xml.Operator;
import com.liuya.db.sql.xml.QueryType;
import com.liuya.db.sql.xml.SimpleValue;
import com.liuya.db.sql.xml.Table;
import com.liuya.db.sql.xml.UserValue;
import com.liuya.db.sql.xml.Value;
import com.liuya.db.sql.xml.types.QueryTypeTypeType;
import com.liuya.db.sql.xml.types.SimpleOperatorType;
import com.liuya.db.sql.xml.types.SimpleValueTypeTypeType;

import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;


/**
 * 设计器模式设计查询
 */
@Controller
@Api(value = "查询策略", description = "查询策略")
@RequestMapping(value = "queryDesign")
public class QueryDesignController extends BaseController {

    @ApiOperation(value = "设计查询策略")
//    @RequiresPermissions("sys.queryPolicy.editPolicy")
    @RequestMapping(value = "/editPolicy")
    public Object editPolicy(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        String oper = req.getParameter("oper");
        String tableAlias = req.getParameter("tableAlias");
        String columnName = req.getParameter("columnName");

        QueryDesignHandler handler = getHandler(req);
        modelMap.addAttribute("queryType", handler.getQuery());
        return "policy/query/design";
    }

    @ApiOperation(value = "跳转到表视图页面 ")
//    @RequiresPermissions("sys.queryPolicy.designTables")
    @RequestMapping(value = "/designTables")
    public String designTables(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        QueryDesignHandler handler = getHandler(req);
        modelMap.addAttribute("handler", handler);
        return "policy/query/tables";
    }

    @ApiOperation(value = "添加表")
//    @RequiresPermissions("sys.queryPolicy.addTable")
    @RequestMapping(value = "/addTable")
    public void addTable(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap) throws IOException {
        QueryDesignHandler handler = getHandler(req);
        String schema = req.getParameter("schema");
        String tableName = req.getParameter("tableName");
        String alias = handler.addTable(schema.trim(), tableName.trim());
        updateHandler(req, handler);

        Gson gson = new Gson();
        String json = gson.toJson(alias);
//        System.out.println(json);
        rep.setContentType("application/json");
        rep.getWriter().print(json);

//        return alias;
        return ;
    }

    @ApiOperation(value = "展示己添加的表")
//    @RequiresPermissions("sys.queryPolicy.viewTable")
    @RequestMapping(value = "/viewTable")
    public Object viewTable(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        String tableAlias = req.getParameter("tableAlias");
        QueryDesignHandler handler = getHandler(req);
        req.setAttribute("handler", handler);
        String schema = "[Default]";
        TableView tableView = null;
        Map tds = handler.getTableDefinitions();

        Table[] tables = handler.getQuery().getQueryTypeSequence().getFrom().getTable();
        for (int i = 0; i < tables.length; i++) {
            Table table = tables[i];
            if (table.getAlias().equals(tableAlias)) {
                req.setAttribute("table", table);
                i = tables.length;
                schema = table.getSchema().equals("")?"[Default]":table.getSchema();
            }
        }

//        updateHandler(req, handler);
        tableView = handler.getTableView( tableAlias );
        modelMap.addAttribute("tableAlias", tableAlias);
        modelMap.addAttribute("tableView", tableView);
        modelMap.addAttribute("schema", schema);
        return "policy/query/table";
    }

    @ApiOperation(value = "获取给定名称的表列")
//    @RequiresPermissions("sys.queryPolicy.getColumn")
    @RequestMapping(value = "/getColumn")
    public Object getColumn(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        String oper = req.getParameter("oper");
        String tableAlias = req.getParameter("tableAlias");
        String columnName = req.getParameter("columnName");
        QueryDesignHandler handler = getHandler(req);
        req.setAttribute("handler", handler);

        Column column = handler.getColumn(tableAlias, columnName);
        String[][] mappingClassPropertyAndTypes = handler.getMappingClassPropertyAndTypes();

        req.setAttribute("column", column);
        req.setAttribute("mappingClassPropertyAndTypes", mappingClassPropertyAndTypes);

        return "policy/query/editColumn";
    }

    @ApiOperation(value = "编辑查询策略")
//    @RequiresPermissions("sys.queryPolicy.getGroupColumn")
    @RequestMapping(value = "/getGroupColumn")
    public Object getGroupColumn(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        String oper = req.getParameter("oper");
        String tableAlias = req.getParameter("tableAlias");
        String columnName = req.getParameter("columnName");
        QueryDesignHandler handler = getHandler(req);
        req.setAttribute("handler", handler);

        Column column = handler.getGroupColumn(tableAlias, columnName);

        req.setAttribute("column", column);
        return "policy/query/editGroupColumn";
    }

    @ApiOperation(value = "编辑查询策略")
//    @RequiresPermissions("sys.queryPolicy.getOrderColumn")
    @RequestMapping(value = "/getOrderColumn")
    public Object getOrderColumn(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        String oper = req.getParameter("oper");
        String tableAlias = req.getParameter("tableAlias");
        String columnName = req.getParameter("columnName");
        QueryDesignHandler handler = getHandler(req);
        req.setAttribute("handler", handler);

        Column column = handler.getOrderColumn(tableAlias, columnName);

        req.setAttribute("column", column);
        return "policy/query/editOrderColumn";
    }

    @ApiOperation(value = "编辑查询策略")
//    @RequiresPermissions("sys.queryPolicy.designGroup")
    @RequestMapping(value = "/designGroup")
    public Object designGroup(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        QueryDesignHandler handler = getHandler(req);
        req.setAttribute("queryType", handler.getQuery());

        return "policy/query/group";
    }

    @ApiOperation(value = "跳转到排序设计页面")
//    @RequiresPermissions("sys.queryPolicy.designOrder")
    @RequestMapping(value = "/designOrder")
    public Object designOrder(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        QueryDesignHandler handler = getHandler(req);
        req.setAttribute("queryType", handler.getQuery());

        return "policy/query/order";
    }

    @ApiOperation(value = "跳转到where子句设计页面")
//    @RequiresPermissions("sys.queryPolicy.designWhere")
    @RequestMapping(value = "/designWhere")
    public Object designWhere(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        QueryDesignHandler handler = getHandler(req);
        req.setAttribute("handler", handler);

        return "policy/query/where";
    }

    @ApiOperation(value = "where子句页面菜单项")
//    @RequiresPermissions("sys.queryPolicy.whereExprContextMenu")
    @RequestMapping(value = "/whereExprContextMenu")
    public Object whereExprContextMenu(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        String oper = req.getParameter("oper");
        String tableAlias = req.getParameter("tableAlias");
        String columnName = req.getParameter("columnName");
        QueryDesignHandler handler = getHandler(req);
        req.setAttribute("handler", handler);

        String nodeId = req.getParameter("nodeId");
        Object item = handler.getWhereExprItem(nodeId);

        req.setAttribute("item", item);
        return "policy/query/whereExprContextMenu";
    }

    @ApiOperation(value = "加载where子句")
//    @RequiresPermissions("sys.queryPolicy.loadWhereExprForm")
    @RequestMapping(value = "/loadWhereExprForm")
    public Object loadWhereExprForm(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        String oper = req.getParameter("oper");
        String tableAlias = req.getParameter("tableAlias");
        String columnName = req.getParameter("columnName");
        QueryDesignHandler handler = getHandler(req);
        req.setAttribute("handler", handler);

        String nodeId = req.getParameter("nodeId");
        // String pId=req.getParameter( "pId" );
        String exprType = req.getParameter("exprType");

        if (!StringUtil.isEmpty(nodeId)) {
            Object obj = handler.getWhereExprItem(nodeId);
            ExpressionGroupTypeItem item = (ExpressionGroupTypeItem) obj;
            req.setAttribute("item", item);

            Object choiceValue = item.getChoiceValue();
            if (choiceValue instanceof BinaryExpression) {
                exprType = "binary";
            } else if (choiceValue instanceof InExpression || choiceValue instanceof NotInExpression) {
                exprType = "in";
            } else if (choiceValue instanceof IsNullExpression || choiceValue instanceof IsNotNullExpression) {
                exprType = "null";
            }
        }

        String[] userFields = AuthUtil.getUserType(req).getUserMetadata().getUserFields();
//        req.setAttribute("userFields", ReflectUtil.reflectJavaBeanFieldNames(SafeUser.class).toArray());
        req.setAttribute("userFields", userFields);

        if ("binary".equals(exprType)) {
            return "policy/query/editWhereBinaryExpr";
        } else if ("in".equals(exprType)) {
            return "policy/query/editWhereInExpr";
        } else if ("null".equals(exprType)) {
            return "policy/query/editWhereNullExpr";
        }

        return "";
    }

    @ApiOperation(value = "返回设计器主页")
//    @RequiresPermissions("sys.queryPolicy.returnMain")
    @RequestMapping(value = "/returnMain")
    public Object returnMain(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        String oper = req.getParameter("oper");
        String tableAlias = req.getParameter("tableAlias");
        String columnName = req.getParameter("columnName");
        QueryDesignHandler handler = getHandler(req);
        req.setAttribute("handler", handler);

        // remove handler from session
        req.getSession().removeAttribute(getHandlerAttributeKey(req));
        return handler.getManagePage();
    }

    @ApiOperation(value = "检查表列")
//    @RequiresPermissions("sys.queryPolicy.checkTableColumns")
    @RequestMapping(value = "/checkTableColumns")
    @ResponseBody
    public Object checkTableColumns(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        String oper = req.getParameter("oper");
        String tableAlias = req.getParameter("tableAlias");
        String columnName = req.getParameter("columnName");
        QueryDesignHandler handler = getHandler(req);
        req.setAttribute("handler", handler);

        handler.addTableColumns(tableAlias);
        updateHandler(req, handler);
        return true;
    }

    @ApiOperation(value = "不检查表列")
//    @RequiresPermissions("sys.queryPolicy.unCheckTableColumns")
    @RequestMapping(value = "/unCheckTableColumns")
    @ResponseBody
    public Object unCheckTableColumns(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        String oper = req.getParameter("oper");
        String tableAlias = req.getParameter("tableAlias");
        String columnName = req.getParameter("columnName");
        QueryDesignHandler handler = getHandler(req);
        req.setAttribute("handler", handler);

        handler.deleteTableColumns(tableAlias);
        updateHandler(req, handler);
        return true;
    }

    @ApiOperation(value = "删除表")
//    @RequiresPermissions("sys.queryPolicy.deleteTable")
    @RequestMapping(value = "/deleteTable")
    @ResponseBody
    public Object deleteTable(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        String oper = req.getParameter("oper");
        String tableAlias = req.getParameter("tableAlias");
        String columnName = req.getParameter("columnName");
        QueryDesignHandler handler = getHandler(req);
        req.setAttribute("handler", handler);

        handler.deleteTable(tableAlias);
        updateHandler(req, handler);
        return true;
    }

    @ApiOperation(value = "设置映射的javabean")
//    @RequiresPermissions("sys.queryPolicy.setMappingClass")
    @RequestMapping(value = "/setMappingClass")
    @ResponseBody
    public Object setMappingClass(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        QueryDesignHandler handler = getHandler(req);
//        req.setAttribute("handler", handler);
        String mappingClass = req.getParameter("mappingClass");
        handler.setMappingClass(mappingClass);
        updateHandler(req, handler);
        return true;
    }

    @ApiOperation(value = "编辑查询策略")
//    @RequiresPermissions("sys.queryPolicy.deleteColumn")
    @RequestMapping(value = "/deleteColumn")
    @ResponseBody
    public Object deleteColumn(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        String oper = req.getParameter("oper");
        String tableAlias = req.getParameter("tableAlias");
        String columnName = req.getParameter("columnName");
        QueryDesignHandler handler = getHandler(req);
        req.setAttribute("handler", handler);

        handler.deleteColumn(tableAlias, columnName);
        updateHandler(req, handler);
        return true;
    }

    @ApiOperation(value = "添加进行映射的列")
//    @RequiresPermissions("sys.queryPolicy.addColumn")
    @RequestMapping(value = "/addColumn")
    @ResponseBody
    public Object addColumn(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        String tableAlias = req.getParameter("tableAlias");
        String columnName = req.getParameter("columnName");
        QueryDesignHandler handler = getHandler(req);

        handler.addColumn(tableAlias, columnName);
        updateHandler(req, handler);
        return true;
    }

    @ApiOperation(value = "更新映射的表列")
    @RequiresPermissions("sys.queryPolicy.updateTableColumn")
    @RequestMapping(value = "/updateTableColumn")
    @ResponseBody
    public Object updateTableColumn(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        String oper = req.getParameter("oper");
        String tableAlias = req.getParameter("tableAlias");
        String columnName = req.getParameter("columnName");
        QueryDesignHandler handler = getHandler(req);

        String function = req.getParameter("function");
        String property = req.getParameter("property");
        boolean readOnly = WebUtil.getBooleanParameter(req, "readOnly", false);

        int index = property.indexOf("<");
        String javaProp = property.substring(0, index - 1).trim();
        String javaType = property.substring(index + 1, property.length() - 1).trim();
        handler.changeColumnMapping(tableAlias, columnName, function, javaProp, javaType, readOnly);

        updateHandler(req, handler);
        return true;
    }

    @ApiOperation(value = "编辑查询策略")
//    @RequiresPermissions("sys.queryPolicy.moveGroupColumn")
    @RequestMapping(value = "/moveGroupColumn")
    @ResponseBody
    public Object moveGroupColumn(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        String oper = req.getParameter("oper");
        String tableAlias = req.getParameter("tableAlias");
        String columnName = req.getParameter("columnName");
        QueryDesignHandler handler = getHandler(req);
        req.setAttribute("handler", handler);

        String direct = req.getParameter("direct");

        handler.moveGroupColumn(direct, tableAlias, columnName);
        updateHandler(req, handler);
        return true;
    }

    @ApiOperation(value = "编辑查询策略")
//    @RequiresPermissions("sys.queryPolicy.deleteGroupColumn")
    @RequestMapping(value = "/deleteGroupColumn")
    @ResponseBody
    public Object deleteGroupColumn(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        String oper = req.getParameter("oper");
        String tableAlias = req.getParameter("tableAlias");
        String columnName = req.getParameter("columnName");
        QueryDesignHandler handler = getHandler(req);

        handler.deleteGroupColumn(tableAlias, columnName);
        updateHandler(req, handler);
        return true;
    }

    @ApiOperation(value = "编辑查询策略")
//    @RequiresPermissions("sys.queryPolicy.editGroupColumn")
    @RequestMapping(value = "/editGroupColumn")
    @ResponseBody
    public Object editGroupColumn(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        String oper = req.getParameter("oper");
        String tableAlias = req.getParameter("tableAlias");
        String columnName = req.getParameter("columnName");
        QueryDesignHandler handler = getHandler(req);
        req.setAttribute("handler", handler);

        String aliasColumn = req.getParameter("aliasColumn");
        int firstIndex = aliasColumn.indexOf("[");
        int lastIndex = aliasColumn.indexOf("]");

        tableAlias = aliasColumn.substring(firstIndex + 1, lastIndex);
        columnName = aliasColumn.substring(lastIndex + 2);

        int index = WebUtil.getIntParameter(req, "index", 0);
        handler.editGroupColumn(index, tableAlias, columnName);
        updateHandler(req, handler);
        return true;
    }

    @ApiOperation(value = "编辑查询策略")
//    @RequiresPermissions("sys.queryPolicy.addGroupColumn")
    @RequestMapping(value = "/addGroupColumn")
    @ResponseBody
    public Object addGroupColumn(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        String oper = req.getParameter("oper");
        String tableAlias = req.getParameter("tableAlias");
        String columnName = req.getParameter("columnName");
        QueryDesignHandler handler = getHandler(req);
        req.setAttribute("handler", handler);

        String aliasColumn = req.getParameter("aliasColumn");
        int firstIndex = aliasColumn.indexOf("[");
        int lastIndex = aliasColumn.indexOf("]");

        tableAlias = aliasColumn.substring(firstIndex + 1, lastIndex);
        columnName = aliasColumn.substring(lastIndex + 2);

        handler.addGroupColumn(tableAlias, columnName);
        updateHandler(req, handler);
        return true;
    }

    @ApiOperation(value = "编辑查询策略")
//    @RequiresPermissions("sys.queryPolicy.moveOrderColumn")
    @RequestMapping(value = "/moveOrderColumn")
    @ResponseBody
    public Object moveOrderColumn(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        String oper = req.getParameter("oper");
        String tableAlias = req.getParameter("tableAlias");
        String columnName = req.getParameter("columnName");
        QueryDesignHandler handler = getHandler(req);
        req.setAttribute("handler", handler);

        String direct = req.getParameter("direct");

        handler.moveOrderColumn(direct, tableAlias, columnName);
        updateHandler(req, handler);
        return true;
    }

    @ApiOperation(value = "编辑查询策略")
//    @RequiresPermissions("sys.queryPolicy.deleteOrderColumn")
    @RequestMapping(value = "/deleteOrderColumn")
    @ResponseBody
    public Object deleteOrderColumn(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        String oper = req.getParameter("oper");
        String tableAlias = req.getParameter("tableAlias");
        String columnName = req.getParameter("columnName");
        QueryDesignHandler handler = getHandler(req);
        req.setAttribute("handler", handler);

        handler.deleteOrderColumn(tableAlias, columnName);
        updateHandler(req, handler);
        return true;
    }

    @ApiOperation(value = "编辑查询策略")
//    @RequiresPermissions("sys.queryPolicy.editOrderColumn")
    @RequestMapping(value = "/editOrderColumn")
    @ResponseBody
    public Object editOrderColumn(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        String oper = req.getParameter("oper");
        String tableAlias = req.getParameter("tableAlias");
        String columnName = req.getParameter("columnName");
        QueryDesignHandler handler = getHandler(req);
        req.setAttribute("handler", handler);

        String aliasColumn = req.getParameter("aliasColumn");
        String orderType = req.getParameter("orderType");
        int firstIndex = aliasColumn.indexOf("[");
        int lastIndex = aliasColumn.indexOf("]");

        tableAlias = aliasColumn.substring(firstIndex + 1, lastIndex);
        columnName = aliasColumn.substring(lastIndex + 2);

        int index = WebUtil.getIntParameter(req, "index", 0);
        handler.editOrderColumn(index, tableAlias, columnName, orderType);

        updateHandler(req, handler);
        return true;
    }

    @ApiOperation(value = "编辑查询策略")
//    @RequiresPermissions("sys.queryPolicy.addOrderColumn")
    @RequestMapping(value = "/addOrderColumn")
    @ResponseBody
    public Object addOrderColumn(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        String oper = req.getParameter("oper");
        String tableAlias = req.getParameter("tableAlias");
        String columnName = req.getParameter("columnName");
        QueryDesignHandler handler = getHandler(req);
        req.setAttribute("handler", handler);

        String aliasColumn = req.getParameter("aliasColumn");
        String orderType = req.getParameter("orderType");
        int firstIndex = aliasColumn.indexOf("[");
        int lastIndex = aliasColumn.indexOf("]");

        tableAlias = aliasColumn.substring(firstIndex + 1, lastIndex);
        columnName = aliasColumn.substring(lastIndex + 2);

        handler.addOrderColumn(tableAlias, columnName, orderType);

        updateHandler(req, handler);
        return true;
    }

    @ApiOperation(value = "加载where子句条件")
//    @RequiresPermissions("sys.queryPolicy.loadWhereExprGroup")
    @RequestMapping(value = "/loadWhereExprGroup")
    @ResponseBody
    public Object loadWhereExprGroup(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        QueryDesignHandler handler = getHandler(req);
        req.setAttribute("handler", handler);
        String xml = handler.getWhere();
        return xml;
    }

    @ApiOperation(value = "编辑查询策略")
//    @RequiresPermissions("sys.queryPolicy.addWhereChildExprGroup")
    @RequestMapping(value = "/addWhereChildExprGroup")
    @ResponseBody
    public Object addWhereChildExprGroup(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        String oper = req.getParameter("oper");
        String tableAlias = req.getParameter("tableAlias");
        String columnName = req.getParameter("columnName");
        QueryDesignHandler handler = getHandler(req);
        req.setAttribute("handler", handler);

        String nodeId = req.getParameter("nodeId");
        String type = req.getParameter("type");

        handler.addWhereChildExprGroup(nodeId, type);

        updateHandler(req, handler);
        return true;
    }

    @ApiOperation(value = "编辑查询策略")
//    @RequiresPermissions("sys.queryPolicy.editWhereExprGroup")
    @RequestMapping(value = "/editWhereExprGroup")
    @ResponseBody
    public Object editWhereExprGroup(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        String oper = req.getParameter("oper");
        String tableAlias = req.getParameter("tableAlias");
        String columnName = req.getParameter("columnName");
        QueryDesignHandler handler = getHandler(req);
        req.setAttribute("handler", handler);

        String nodeId = req.getParameter("nodeId");
        String type = req.getParameter("type");

        handler.editWhereExprGroup(nodeId, type);

        updateHandler(req, handler);
        return true;
    }

    @ApiOperation(value = "编辑查询策略")
//    @RequiresPermissions("sys.queryPolicy.deleteWhereExpr")
    @RequestMapping(value = "/deleteWhereExpr")
    @ResponseBody
    public Object deleteWhereExpr(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        String oper = req.getParameter("oper");
        String tableAlias = req.getParameter("tableAlias");
        String columnName = req.getParameter("columnName");
        QueryDesignHandler handler = getHandler(req);
        req.setAttribute("handler", handler);

        String nodeId = req.getParameter("nodeId");

        handler.deleteWhereExpr(nodeId);

        updateHandler(req, handler);
        return true;
    }

    @ApiOperation(value = "编辑查询策略")
//    @RequiresPermissions("sys.queryPolicy.addWhereExpr")
    @RequestMapping(value = "/addWhereExpr")
    @ResponseBody
    public Object addWhereExpr(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        String oper = req.getParameter("oper");
        String tableAlias = req.getParameter("tableAlias");
        String columnName = req.getParameter("columnName");
        QueryDesignHandler handler = getHandler(req);
        req.setAttribute("handler", handler);

        String pId = req.getParameter("pId");
        String exprType = req.getParameter("exprType");

        if ("binary".equals(exprType)) {
            BinaryExpression expr = getBinaryExpression(req);
            handler.addBinaryExpression(expr, pId);
        } else if ("null".equals(exprType)) {
            Column column = getWhereExprInColumn(req);

            String operator = req.getParameter("operator");
            handler.addNullExpression(column, operator, pId);
        }

        updateHandler(req, handler);
        return true;
    }

    @ApiOperation(value = "编辑查询策略")
//    @RequiresPermissions("sys.queryPolicy.editWhereExpr")
    @RequestMapping(value = "/editWhereExpr")
    @ResponseBody
    public Object editWhereExpr(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        String oper = req.getParameter("oper");
        String tableAlias = req.getParameter("tableAlias");
        String columnName = req.getParameter("columnName");
        QueryDesignHandler handler = getHandler(req);
        req.setAttribute("handler", handler);

        String nodeId = req.getParameter("nodeId");
        String exprType = req.getParameter("exprType");

        if ("binary".equals(exprType)) {
            BinaryExpression expr = getBinaryExpression(req);
            handler.editBinaryExpression(expr, nodeId);
        } else if ("null".equals(exprType)) {
            Column column = getWhereExprInColumn(req);

            String operator = req.getParameter("operator");
            handler.editNullExpression(column, operator, nodeId);
        }

        updateHandler(req, handler);
        return true;
    }

    @ApiOperation(value = "保存查询策略")
//    @RequiresPermissions("sys.queryPolicy.save")
    @RequestMapping(value = "/save")
    @ResponseBody
    public Object save(HttpServletRequest req, HttpServletResponse rep, ModelMap modelMap){
        QueryDesignHandler handler = getHandler(req);
        // remove handler from session
        req.getSession().removeAttribute(getHandlerAttributeKey(req));
        String id = WebUtil.getStringParameter(req, "id", "-23");
        QueryManagerService queryManager = (QueryManagerService) SpringUtils.getBean("queryManagerService");

        boolean result = handler.save(id, queryManager);
        updateHandler(req, handler);
        return result;
    }

    private Column getWhereExprInColumn(HttpServletRequest req) {
        String columnWithAlias = req.getParameter("column");
        int index1 = columnWithAlias.indexOf("[");
        int index2 = columnWithAlias.indexOf("]");
        int index3 = columnWithAlias.lastIndexOf(".");

        String exprTableAlias = columnWithAlias.substring(index1 + 1, index2).trim();
        String exprColumnName = columnWithAlias.substring(index3 + 1).trim();

        Column column = new Column();
        column.setName(exprColumnName);
        column.setTableAlias(exprTableAlias);

        return column;
    }

    private BinaryExpression getBinaryExpression(HttpServletRequest req) {
        Operand innerOperand1 = getOperand(req, 1);
        Operand innerOperand2 = getOperand(req, 2);
        String strOperator = req.getParameter("operator");

        BinaryExpression expr = new BinaryExpression();
        Operand1 operand1 = new Operand1();
        operand1.setOperand(innerOperand1);
        Operand2 operand2 = new Operand2();
        operand2.setOperand(innerOperand2);
        Operator operator = new Operator();
        operator.setSimpleOperator(SimpleOperatorType.valueOf(strOperator));

        expr.setOperand1(operand1);
        expr.setOperand2(operand2);
        expr.setOperator(operator);
        return expr;
    }

    private Operand getOperand(HttpServletRequest req, int i) {
        String type = req.getParameter("operand" + i + "Type");

        Operand operand = new Operand();
        if ("column".equals(type)) {
            String columnWithAlias = req.getParameter("column" + i);
            int index1 = columnWithAlias.indexOf("[");
            int index2 = columnWithAlias.indexOf("]");
            int index3 = columnWithAlias.lastIndexOf(".");

            String tableAlias = columnWithAlias.substring(index1 + 1, index2).trim();
            String columnName = columnWithAlias.substring(index3 + 1).trim();

            Column column = new Column();
            column.setName(columnName);
            column.setTableAlias(tableAlias);
            operand.setColumn(column);
        } else if ("contextValue".equals(type)) {
            String str = req.getParameter("contextValue" + i);

            ContextValue ctxValue = new ContextValue();
            ctxValue.setKey(str);
            Value value = new Value();
            value.setContextValue(ctxValue);
            operand.setValue(value);
        } else if ("userValue".equals(type)) {
            String str = req.getParameter("userValue" + i);

            UserValue uValue = new UserValue();
            uValue.setKey(str);
            Value value = new Value();
            value.setUserValue(uValue);
            operand.setValue(value);
        } else if ("simpleValue".equals(type)) {
            String str = req.getParameter("simpleValue" + i);
            String simpleValueType = req.getParameter("simpleValueType" + i);
            SimpleValue sValue = new SimpleValue();
            sValue.setContent(str);
            sValue.setType(SimpleValueTypeTypeType.valueOf(simpleValueType));

            Value value = new Value();
            value.setSimpleValue(sValue);
            operand.setValue(value);
        }

        return operand;
    }

    private QueryDesignHandler createHandler(HttpServletRequest req) {
        String id = WebUtil.getStringParameter(req, "id", "0");
        QueryManagerService queryManager = (QueryManagerService) SpringUtils.getBean("queryManagerService");
        SafeQuery query = queryManager.getQuery(id);

        com.liuya.db.sql.xml.QueryType xmlQuery;
        try {
            xmlQuery = com.liuya.db.sql.xml.Query.unmarshal(new StringReader(query.getXmlContent()));
        } catch (Exception e) {
            throw new AuthException(e);
        }

        return new QueryDesignHandler(xmlQuery);
    }

    public String getHandlerAttributeKey(HttpServletRequest req) {
        int id = WebUtil.getIntParameter(req, "id", 0);
        return "_$safeQuery_" + id;
    }

    private void updateHandler(HttpServletRequest req, Object handler) {
        String key = getHandlerAttributeKey(req);
        HttpSession session = req.getSession();
        session.setAttribute(key, handler);
    }

    private QueryDesignHandler getHandler(HttpServletRequest req) {
        String oper = req.getParameter("oper");
        String key = getHandlerAttributeKey(req);
        QueryDesignHandler handler = null;
        HttpSession session = req.getSession();
        Object obj = session.getAttribute(key);

        if (obj == null || "loadFresh".equals(oper)) {
            handler = createHandler(req);
            // save into session, will be removed when policy is saved
            session.setAttribute(key, handler);
        } else if (obj instanceof QueryRawHandler) {
            QueryRawHandler rawHandler = (QueryRawHandler) obj;
            QueryType query = rawHandler.getQuery();
            handler = new QueryDesignHandler(query);
            req.getSession().setAttribute(key, handler);

            // set to design sql type
            query.setIsRawSQL(false);
            query.setType(QueryTypeTypeType.SQL);
        } else if (obj instanceof QueryTestHandler) {
            QueryTestHandler rawHandler = (QueryTestHandler) obj;
            QueryType query = rawHandler.getQuery();
            handler = new QueryDesignHandler(query);
            req.getSession().setAttribute(key, handler);
        } else {
            handler = (QueryDesignHandler) obj;
        }

        return handler;
    }


}
